package com.houweishi.module.oaEntry.service.impl;

import com.alibaba.fastjson.JSON;
import com.houweishi.common.constant.Constants;
import com.houweishi.common.constant.HttpStatus;
import com.houweishi.common.core.domain.AjaxResult;
import com.houweishi.common.core.domain.entity.SysUser;
import com.houweishi.common.core.domain.model.LoginUser;
import com.houweishi.common.exception.base.BaseException;
import com.houweishi.common.utils.DateUtils;
import com.houweishi.common.utils.SecurityUtils;
import com.houweishi.module.bizSerialNum.service.IBizSerialNumTService;
import com.houweishi.module.copy.domain.BizCopy;
import com.houweishi.module.copy.mapper.BizCopyMapper;
import com.houweishi.module.oaEntry.domain.OaEntry;
import com.houweishi.module.oaEntry.domain.OaEntryEducationExperience;
import com.houweishi.module.oaEntry.domain.OaEntryWorkExperience;
import com.houweishi.module.oaEntry.mapper.OaEntryMapper;
import com.houweishi.module.oaEntry.service.IOaEntryService;
import com.houweishi.module.record.domain.BizApprovalRecord;
import com.houweishi.module.record.mapper.BizApprovalRecordMapper;
import com.houweishi.module.record.service.IBizApprovalRecordService;
import com.houweishi.module.staff.domain.BizStaff;
import com.houweishi.module.staff.service.IBizStaffService;
import com.houweishi.module.syTableRecord.service.ISyTableRecordTService;
import com.houweishi.system.mapper.SysUserMapper;
import com.houweishi.ws.po.Message;
import com.houweishi.ws.service.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 入职申请Service业务层处理
 * 
 * @author yqq
 * @date 2023-07-05
 */
@Service
public class OaEntryServiceImpl implements IOaEntryService 
{

    private static final Logger LOGGER = LoggerFactory.getLogger(OaEntryServiceImpl.class);
    @Resource
    private OaEntryMapper oaEntryMapper;

    /**
     * 流程单号生成
     */
    @Resource
    private IBizSerialNumTService iBizSerialNumTService;

    /**
     * 审批记录
     */
    @Resource
    private BizApprovalRecordMapper bizApprovalRecordMapper;

    /**
     * 抄送记录
     */
    @Resource
    private BizCopyMapper bizCopyMapper;

    /**
     * 用户Mapper
     */
    @Resource
    private SysUserMapper sysUserMapper;

    /**
     * 审批记录Service
     */
    @Resource
    private IBizApprovalRecordService iBizApprovalRecordService;

    /**
     * 记录表
     */
    @Resource
    private ISyTableRecordTService iSyTableRecordTService;

    /**
     * 消息推送Server
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 员工Service
     */
    @Resource
    private IBizStaffService iBizStaffService;

    /**
     * 查询入职申请
     * 
     * @param id 入职申请主键
     * @return 入职申请
     */
    @Override
    public OaEntry selectOaEntryById(Long id)
    {
        return oaEntryMapper.selectOaEntryById(id);
    }

    /**
     * 查询入职申请列表
     * 
     * @param oaEntry 入职申请
     * @return 入职申请
     */
    @Override
    public List<OaEntry> selectOaEntryList(OaEntry oaEntry)
    {
        return oaEntryMapper.selectOaEntryList(oaEntry);
    }

    /**
     * 新增入职申请
     * 
     * @param oaEntry 入职申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertOaEntry(OaEntry oaEntry)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请先登录");
        }
        // 判断是否再提交
        if (StringUtils.isNotBlank(oaEntry.getSerialNum())) {
            oaEntry.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaEntry.setUpdateBy(loginUser.getUsername());
            oaEntry.setBusinessStatus(Constants.APPROVE);
            // 修改报销单，审批记录表，抄送
            return resubmitReimburse(oaEntry, loginUser);
        } else {
            // 获取流水单号
            String serialNum = iBizSerialNumTService.generateSerialNum("RZSQ");
            oaEntry.setSerialNum(serialNum);
            oaEntry.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaEntry.setUpdateBy(loginUser.getUsername());
            oaEntry.setCreateBy(loginUser.getUsername());
            oaEntry.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaEntry.setBusinessStatus(Constants.APPROVE);
            oaEntryMapper.insertOaEntry(oaEntry);
            iSyTableRecordTService.saveEntityAndTable(oaEntry,serialNum);
            // 插入审批记录表
            return setApprovalRecord(oaEntry, loginUser);
        }
    }
    /**
     * 重提交：修改表单，审批记录表，抄送
     * @param oaEntry
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult resubmitReimburse(OaEntry oaEntry, LoginUser loginUser) {
        //修改报销单
        oaEntryMapper.updateOaEntry(oaEntry);
        //删除审批记录
        bizApprovalRecordMapper.deleteBizApprovalRecordBySerialNum(oaEntry.getSerialNum());
        // 删除抄送
        bizCopyMapper.deleteBizCopyMapperBySerialNum(oaEntry.getSerialNum());
        //删除工作经历
        oaEntryMapper.deleteOaEntryWorkExperienceByEntryId(oaEntry.getId());
        //删除教育经历
        oaEntryMapper.deleteOaEntryEducationExperienceByEntryId(oaEntry.getId());
        //新增审批及抄送
        return setApprovalRecord(oaEntry,loginUser);
    }

    /**
     * 插入审批记录表
     *
     * @param oaEntry
     */
    @Transactional(rollbackFor = Exception.class)
    AjaxResult setApprovalRecord(OaEntry oaEntry, LoginUser loginUser) {
        List<BizApprovalRecord> bizApprovalRecords;
        //是否使用模板
        String typeStatus = oaEntry.getTypeStatus();
        if ("0".equals(typeStatus)){
            //使用模板
            bizApprovalRecords= iBizApprovalRecordService.approvalTemplate(loginUser, oaEntry.getSerialNum(),"入职");
        }else{
            //不使用模板，自定义
            bizApprovalRecords = addApprovalRecord(oaEntry, loginUser);
        }
        bizApprovalRecordMapper.insertBatchBizApprovalRecord(bizApprovalRecords);

        //批量新增工作经验
        batchOaEntryWorkExperienceList(oaEntry);

        //批量新增教育经历
        batchOaEntryEducationExperience(oaEntry);

        // 增加抄送人
        addCopyPeople(oaEntry);

        // 推送消息
        List<BizApprovalRecord> messageList = bizApprovalRecords.stream()
                .filter(a -> a.getSequence() == 2)
                .collect(Collectors.toList());
        sendMessage(messageList.get(0).getApproverId(), messageList.get(0).getApproverName(), oaEntry);

        return new AjaxResult(HttpStatus.SUCCESS, "新增入职申请审批记录成功");
    }

    /**
     * 批量新增教育经历
     * @param oaEntry
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchOaEntryEducationExperience(OaEntry oaEntry) {
        List<OaEntryEducationExperience> oaEntryEducationExperienceList = oaEntry.getOaEntryEducationExperienceList();
        Long id = oaEntry.getId();
        if (!CollectionUtils.isEmpty(oaEntryEducationExperienceList)){
            List<OaEntryEducationExperience> list = new ArrayList<>();
            for (OaEntryEducationExperience oaEntryEducationExperience : oaEntryEducationExperienceList) {
                oaEntryEducationExperience.setEntryId(id);
                oaEntryEducationExperience.setUpdateBy(oaEntry.getUpdateBy());
                oaEntryEducationExperience.setUpdateTime(oaEntry.getUpdateTime());
                oaEntryEducationExperience.setCreateBy(oaEntry.getCreateBy());
                oaEntryEducationExperience.setUpdateTime(oaEntry.getCreateTime());
                list.add(oaEntryEducationExperience);
            }
            if (list.size()>0){
                oaEntryMapper.batchOaEntryEducationExperience(list);
            }
        }

    }

    /**
     * 批量新增工作经历
     * @param oaEntry
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchOaEntryWorkExperienceList(OaEntry oaEntry) {
        List<OaEntryWorkExperience> oaEntryWorkExperienceList = oaEntry.getOaEntryWorkExperienceList();
        Long id = oaEntry.getId();
        if (!CollectionUtils.isEmpty(oaEntryWorkExperienceList))
        {
            List<OaEntryWorkExperience> list = new ArrayList<>();
            for (OaEntryWorkExperience oaEntryWorkExperience : oaEntryWorkExperienceList)
            {
                oaEntryWorkExperience.setEntryId(id);
                oaEntryWorkExperience.setUpdateBy(oaEntry.getUpdateBy());
                oaEntryWorkExperience.setUpdateTime(oaEntry.getUpdateTime());
                oaEntryWorkExperience.setCreateBy(oaEntry.getCreateBy());
                oaEntryWorkExperience.setUpdateTime(oaEntry.getCreateTime());
                list.add(oaEntryWorkExperience);
            }
            if (list.size() > 0)
            {
                oaEntryMapper.batchOaEntryWorkExperience(list);
            }
        }
    }

    /**
     * 推送消息到前端
     * @param userId
     * @param userName
     * @param oaEntry
     */
    private void sendMessage(Long userId, String userName, OaEntry oaEntry) {
        try {
            //发送消息
            Message message = new Message();
            message.setFromId(oaEntry.getApplyUserId());
            message.setFromName(oaEntry.getApplyUserName());
            message.setNextNodeId(userId);
            message.setNextNodeName(userName);
            message.setStatus(Constants.COMPLETED);
            message.setSerialNum(oaEntry.getSerialNum());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("新增入职申请推送失败",e);
        }
    }

    /**
     * 自定义，添加审批记录
     * @return
     */
    public List<BizApprovalRecord> addApprovalRecord(OaEntry oaEntry,LoginUser loginUser){
        List<BizApprovalRecord> bizApprovalRecords = new ArrayList<>();
        int sequence = 1;
        // 保存发起人
        BizApprovalRecord initiatorRecord = createApprovalRecord(oaEntry, null, loginUser);
        initiatorRecord.setSequence(sequence);
        initiatorRecord.setSerialNum(oaEntry.getSerialNum());
        initiatorRecord.setApprovalStatus(Constants.COMPLETED);
        initiatorRecord.setTypeOperation(Constants.AGREE);
        initiatorRecord.setBusinessStatus(Constants.APPROVE);
        bizApprovalRecords.add(initiatorRecord);

        // 字符串分割，并把String[]转换为list(传入了一个字符串类型的数据）
        if (StringUtils.isEmpty(oaEntry.getApprover())) {
            throw new BaseException("请选审批人");
        }
        String[] approvers = oaEntry.getApprover().split(",");
        List<Long> idList = Arrays.stream(approvers).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        // 获取详细审批人信息
        List<SysUser> sysUserList = sysUserMapper.selectUserByUserIds(idList);
        if (idList.size() != sysUserList.size()) {
            throw new BaseException("新增入职申请审批人有误");
        }
        // 根据职位级别降级排序
        sysUserList.sort(Comparator.comparingLong(SysUser::getPositionLevel).reversed());

        // 增加审批记录
        if (!CollectionUtils.isEmpty(sysUserList)) {
            for (int i = 0; i < sysUserList.size(); i++) {
                SysUser sysUser = sysUserMapper.selectUserById(sysUserList.get(i).getUserId());
                if (Objects.isNull(sysUser)){
                    throw new BaseException("新增入职申请审批人信息有误");
                }
                BizApprovalRecord approvalRecord = createApprovalRecord(oaEntry, sysUser, null);
                if (i == 0) {
                    approvalRecord.setApprovalStatus(Constants.APPROVE);
                } else {
                    approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
                }
                sequence++;
                approvalRecord.setSequence(sequence);
                bizApprovalRecords.add(approvalRecord);
            }
        }
        return bizApprovalRecords;
    }

    /**
     * 设置审批记录信息
     *
     * @param oaEntry
     * @param sysUser
     * @return
     */
    public BizApprovalRecord createApprovalRecord(OaEntry oaEntry, SysUser sysUser, LoginUser loginUser) {
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        if (null != sysUser) {
            bizApprovalRecord.setApproverId(sysUser.getUserId());
            bizApprovalRecord.setApproverName(sysUser.getUserName());
            bizApprovalRecord.setPositionLevel(sysUser.getPositionLevel());
        }
        if (null != loginUser) {
            bizApprovalRecord.setApproverId(loginUser.getUserId());
            bizApprovalRecord.setApproverName(loginUser.getUsername());
        }
        bizApprovalRecord.setSubscribePatternName("入职");
        bizApprovalRecord.setSerialNum(oaEntry.getSerialNum());
        bizApprovalRecord.setApplicationId(oaEntry.getId());
        bizApprovalRecord.setUserId(oaEntry.getApplyUserId());
        bizApprovalRecord.setUsername(oaEntry.getApplyUserName());
        bizApprovalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        bizApprovalRecord.setUpdateBy(oaEntry.getApplyUserName());
        bizApprovalRecord.setCreateBy(oaEntry.getApplyUserName());
        bizApprovalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return bizApprovalRecord;
    }


    /**
     * 添加抄送人
     * @param oaEntry
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopyPeople(OaEntry oaEntry) {
        if (StringUtils.isNoneBlank(oaEntry.getCopyerId())){
            //字符串分割，并把String[]转换为list，（抄送人id）
            String[] copyerIds = oaEntry.getCopyerId().split(",");
            List<String> copyerIdList = Arrays.stream(copyerIds).collect(Collectors.toList()) ;
            //抄送记录表
            if(!CollectionUtils.isEmpty(copyerIdList)){
                copyerIdList.forEach(id->{
                    BizCopy bizCopy = new BizCopy();
                    SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(id));
                    bizCopy.setApplicationId(oaEntry.getId());
                    bizCopy.setCopyerId(sysUser.getUserId());
                    bizCopy.setCopyerName(sysUser.getUserName());
                    bizCopy.setPositionLevel(sysUser.getPositionLevel());
                    bizCopy.setUserId(oaEntry.getApplyUserId());
                    bizCopy.setUsername(oaEntry.getApplyUserName());
                    bizCopy.setSerialNum(oaEntry.getSerialNum());
                    bizCopy.setCopyerStatus("0");
                    bizCopy.setCreateTime(DateUtils.getNowDate());
                    bizCopyMapper.insertBizCopy(bizCopy);
                });
            }
        }
    }


    /**
     * 修改入职申请
     * 
     * @param oaEntry 入职申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateOaEntry(OaEntry oaEntry)
    {
        oaEntry.setUpdateTime(DateUtils.getNowDate());
        oaEntryMapper.deleteOaEntryWorkExperienceByEntryId(oaEntry.getId());
        oaEntryMapper.deleteOaEntryEducationExperienceByEntryId(oaEntry.getId());
        batchOaEntryEducationExperience(oaEntry);
        batchOaEntryWorkExperienceList(oaEntry);
        return oaEntryMapper.updateOaEntry(oaEntry);
    }

    /**
     * 批量删除入职申请
     * 
     * @param ids 需要删除的入职申请主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteOaEntryByIds(Long[] ids)
    {
        oaEntryMapper.deleteOaEntryEducationExperienceByEntryIds(ids);
        oaEntryMapper.deleteOaEntryWorkExperienceByEntryIds(ids);
        return oaEntryMapper.deleteOaEntryByIds(ids);
    }

    /**
     * 删除入职申请信息
     * 
     * @param id 入职申请主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteOaEntryById(Long id)
    {
        oaEntryMapper.deleteOaEntryWorkExperienceByEntryId(id);
        oaEntryMapper.deleteOaEntryEducationExperienceByEntryId(id);
        return oaEntryMapper.deleteOaEntryById(id);
    }

    /**
     * 入职申请成功，新增员工信息，通讯记录
     * @param bizApprovalRecord
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addStaffInfo(BizApprovalRecord bizApprovalRecord) {
        //   获取入职信息
        OaEntry oaEntry = new OaEntry();
        oaEntry.setSerialNum(bizApprovalRecord.getSerialNum());
        List<OaEntry> oaEntries = oaEntryMapper.selectOaEntryList(oaEntry);
        if (CollectionUtils.isEmpty(oaEntries)){
            throw new BaseException("查询入职申请集合为空");
        }
        //    新增员工信息
        OaEntry entry = oaEntries.get(0);
        BizStaff bizStaff = new BizStaff();
        bizStaff.setName(entry.getUserName());
        bizStaff.setGender(entry.getSex());
        bizStaff.setAge(entry.getAge());
        bizStaff.setStaffRank(entry.getRankName());
        bizStaff.setPost(entry.getPost());
        bizStaff.setPostId(entry.getPostId());
        bizStaff.setCompany(entry.getCompany());
        bizStaff.setDept(entry.getDeptId());
        bizStaff.setDeptName(entry.getDeptName());
        bizStaff.setBirthday(entry.getBirthday());
        bizStaff.setNativePlace(entry.getNativePlace());
        bizStaff.setPoliticalOutlook(entry.getPoliticalStatus());
        bizStaff.setMarriage(entry.getMaritalStatus());
        bizStaff.setHealthStatus(entry.getHealth());
        bizStaff.setIdCardNumber(entry.getIdentification());
        bizStaff.setEducation(entry.getEducational());
        bizStaff.setTelephone(entry.getPhoneNum());
        bizStaff.setContactName(entry.getEmergencyContact());
        bizStaff.setRelationship(entry.getOwnership());
        bizStaff.setContactTelephone(entry.getEmergencyPhone());
        bizStaff.setSkill(entry.getSkill());
        bizStaff.setEntryTime(entry.getEntryDate());
        bizStaff.setBank(entry.getBankDeposit());
        bizStaff.setBankCardNo(entry.getBankAccountNumber());
        bizStaff.setUserId(entry.getUserId());
        bizStaff.setUserName(entry.getUserName());
        bizStaff.setStatus("1");
        //  教育经验
        List<OaEntryEducationExperience> oaEntryEducationExperienceList = entry.getOaEntryEducationExperienceList();
        if(!CollectionUtils.isEmpty(oaEntryEducationExperienceList)){
            OaEntryEducationExperience oaEntryEducationExperience = oaEntryEducationExperienceList.get(0);
            bizStaff.setAdmissionTime(oaEntryEducationExperience.getStartDate());
            bizStaff.setGraduationTime(oaEntryEducationExperience.getEndDate());
            bizStaff.setGraduationSchool(oaEntryEducationExperience.getSchool());
            bizStaff.setSpeciality(oaEntryEducationExperience.getProfession());
        }
        iBizStaffService.insertBizStaff(bizStaff);
        //  增加打卡记录
        iBizStaffService.insertUserClockingBinding(bizStaff);

    }
}
